
package com.lmx.persistence.service;

import com.lmx.common.constants.ICommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.common.util.PropertiesFileUtil;
import com.lmx.repoDomain.tmodel.ApplyWorktime;
import com.lmx.repoDomain.tmodel.CsCustomer;
import com.lmx.repoDomain.tmodel.Customer;
import com.lmx.repoDomain.tmodel.Interface;
import com.lmx.repoDomain.tmodel.Message;
import com.lmx.repoDomain.tmodel.PageInfo;
import com.lmx.repoDomain.tmodel.ReqLog;
import com.lmx.repoDomain.tmodel.Sign;
import com.lmx.repoDomain.tmodel.Task;
import com.lmx.repoDomain.tmodel.UserSession;
import com.lmx.repoDomain.tmodel.UserTask;
import com.lmx.repoDomain.tmodel.Workorder;
import com.lmx.repoDomain.tmodel.Worktime;
//import com.lmx.repoDomain.tmodel.*;
import com.lmx.repoDomain.tmodel.business.User;//huibati
import io.katharsis.queryParams.QueryParams;
import io.katharsis.queryParams.RestrictedPaginationKeys;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 通用数据处理
 * 
 * @author Administrator
 * @version 1.00
 */
@Service
@Scope("prototype")
public class DataProcessService<T> {
	private Log logger = LogFactory.getLog(this.getClass());
	@Autowired
	private GenericService dslJpaService;
	@PersistenceContext
	private EntityManager em;
	@Autowired
	private CommonService commonService;

	private Properties properties = PropertiesFileUtil.getProperties("application.properties");

	/**
	 * taskExtend 更新数据(已招客服数量)
	 */
	@Transactional
	public void updateCsNum(UserTask userTask) {
		String typecode = userTask.getStatus().getTypecode();
		if (typecode != null && "taskApplySucc".equals(typecode)) {
			// 查询已招客服数量
			int num = (int) (long) this.em
					.createQuery("select count(u.id) from UserTask u where u.task.id = ?1 and u.status.id = ?2")
					.setParameter(1, userTask.getTask().getId())
					.setParameter(2, ActionContextHolder.getDicctypeHolder().get("taskApplySucc").getId())
					// .getResultList().size();
					.getSingleResult();
			// 修改已招客服数量
			this.em.createQuery("update TaskExtend t set t.csHave = ?1 where t.id = ?2").setParameter(1, num)
					.setParameter(2, userTask.getTask().getExtendIfo().getId()).executeUpdate();
		}
	}

	/**
	 * 查询已招客服是否已满
	 * 
	 * @param taskId
	 * @return
	 */
	public boolean isNeed(Long taskId) {
		boolean flag = true;
		Task task = this.em.find(Task.class, taskId);
		Integer need = task.getExtendIfo().getCsNeed();
		Integer have = task.getExtendIfo().getCsHave();
		if (need == null || (have != null && have >= need)) {
			flag = false;
		}
		return flag;
	}

	/**
	 * 更新签到状态
	 */
	@Transactional
	public UserTask updateSignStatus(UserTask userTask) {
		short signststus = userTask.getSignstatus();
		int clientSigntime = userTask.getClientSigntime();
		if (clientSigntime <= 0)
			return userTask;
		logger.debug("更新签到状态 ：" + ICommonConstants.SIGNSTATUS.values()[signststus].label());

		/*
		 * //更新userTask签到状态 String queryUserTask =
		 * "UPDATE UserTask t set t.signstatus = ?1 , t.clientSigntime = ?2 WHERE t.id = ?3"
		 * ; Query qUserTask = this.em.createQuery(queryUserTask);
		 * qUserTask.setParameter(1,signststus);
		 * qUserTask.setParameter(2,clientSigntime);
		 * qUserTask.setParameter(3,userTask.getId());
		 * qUserTask.executeUpdate();
		 */
		dslJpaService.setEntityClass(UserTask.class);
		userTask = (UserTask) dslJpaService.findOne(userTask.getId());
		userTask.setSignstatus(signststus);
		userTask.setClientSigntime(clientSigntime);
		logger.debug("signststus : " + signststus);
		if (signststus == ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal()) { // 签出
			logger.debug("签出---------------------------------------------------------");
			userTask.setNearestSignoutTime(CommonUtil.getCurrTimes());// 修改最近签出时间
			dslJpaService.setEntityClass(UserTask.class);
			userTask = (UserTask) dslJpaService.update(userTask);

			// 更新签到表
			Sign sign = new Sign();
			sign.setSignTime(clientSigntime);
			sign.setSignType((short) ICommonConstants.SIGNTYPE.SIGNOUT.ordinal());
			sign.setTask(userTask.getTask());
			sign.setUser(userTask.getUser());
			dslJpaService.setEntityClass(Sign.class);
			dslJpaService.create(sign);
			logger.debug("增加签出记录");

			// 更新applyWorktime
			String queryApply = "SELECT a FROM ApplyWorktime a WHERE a.userTask.id = " + userTask.getId();
			Query qApply = this.em.createQuery(queryApply);
			List listApply = qApply.getResultList();
			for (int i = 0; i < listApply.size(); i++) {
				ApplyWorktime applyWorktime = (ApplyWorktime) listApply.get(i);
				if (applyWorktime.getSignStatus() != ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal()) {
					applyWorktime.setSignStatus((short) ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal());
					dslJpaService.setEntityClass(ApplyWorktime.class);
					dslJpaService.update(applyWorktime);
				}
			}
			logger.debug("更新applyWorktime");

		} else if (signststus == ICommonConstants.SIGNSTATUS.ALREADYSIGNED.ordinal()) {// 签入
			logger.debug("签入---------------------------------------------------------");
			userTask.setNearestSigninTime(CommonUtil.getCurrTimes());// 修改最近签入时间
			dslJpaService.setEntityClass(UserTask.class);
			userTask = (UserTask) dslJpaService.update(userTask);

			// 更新签到表
			Sign sign = new Sign();
			sign.setSignTime(clientSigntime);
			sign.setSignType((short) ICommonConstants.SIGNTYPE.SIGNIN.ordinal());
			sign.setTask(userTask.getTask());
			sign.setUser(userTask.getUser());
			dslJpaService.setEntityClass(Sign.class);
			dslJpaService.create(sign);
			logger.debug("增加签入记录");

			// 更新ApplyWorktime 签到状态
			Date date = new Date((long) (clientSigntime) * 1000);
			int hour = date.getHours();
			String queryStr = "SELECT a FROM ApplyWorktime a WHERE a.userTask.id = " + userTask.getId();
			Query q = this.em.createQuery(queryStr);
			List list = q.getResultList();
			for (int i = 0; i < list.size(); i++) {
				ApplyWorktime applyWorktime = (ApplyWorktime) list.get(i);
				Worktime worktime = applyWorktime.getWorktime();
				if (worktime.getBeginHour() < hour && worktime.getEndHour() > hour) {
					if (applyWorktime.getSignStatus() == null
							|| applyWorktime.getSignStatus() != ICommonConstants.SIGNSTATUS.ALREADYSIGNED.ordinal()) {
						applyWorktime.setSignStatus((short) ICommonConstants.SIGNSTATUS.ALREADYSIGNED.ordinal());
						dslJpaService.setEntityClass(ApplyWorktime.class);
						dslJpaService.update(applyWorktime);
					}
				} else {
					if (applyWorktime.getSignStatus() == null
							|| applyWorktime.getSignStatus() != ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal()) {
						applyWorktime.setSignStatus((short) ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal());
						dslJpaService.setEntityClass(ApplyWorktime.class);
						dslJpaService.update(applyWorktime);
					}
				}
			}
			logger.debug("更新applyWorktime");

		}
		return userTask;

	}

	/**
	 * 更新工单表
	 * 
	 * @param workorder
	 */
	@Transactional
	public void updateWorkorder(Workorder workorder) {
		this.em.merge(workorder);
	}

	/**
	 * 根据id获取User
	 */
	public User findUserById(String uId) {
		if (uId == null || StringUtils.isBlank(uId)) {
			return null;
		}
		return this.em.find(User.class, Long.parseLong(uId));
	}

	/**
	 * 添加userTask表关联表数据
	 */
	public void addUserTask(UserTask userTask) {
		logger.debug("添加userTask 关联数据 userTaskId ：" + userTask.getId());
		// 默认所有时段全部申请
		dslJpaService.setEntityClass(Worktime.class);
		ArrayList<Worktime> worktimes = (ArrayList<Worktime>) dslJpaService.findAll();
		logger.debug("worktimes.size() : " + worktimes.size());
		for (int i = 0; i < worktimes.size(); i++) {
			logger.debug("添加applyWorktime: " + worktimes.get(i).getBeginHour() + ":" + worktimes.get(i).getEndHour());
			ApplyWorktime applyWorktime = new ApplyWorktime();
			applyWorktime.setUserTask(userTask);
			applyWorktime.setWorktime(worktimes.get(i));
			applyWorktime.setSignStatus((short) ICommonConstants.SIGNSTATUS.NOTSIGN.ordinal());// 默认未签到
			dslJpaService.setEntityClass(ApplyWorktime.class);
			dslJpaService.create(applyWorktime);
		}
	}

	/**
	 * 通用接口参数解析入口
	 */
	public ArrayList<Interface> interfaceAnalysis(final QueryParams requestParams) {
		ArrayList<Interface> interfaces = new ArrayList<Interface>();
		// 获取参数map
		Map<String, String> keyMap = CommonUtil.getKeyMapByFilter(requestParams);
		// method callEnd(通话结束),
		if (StringUtils.isNotBlank(keyMap.get("method")) && "platformProportion".equals(keyMap.get("method"))) {
			Interface inter = new Interface();
			double proportion = commonService.getProportion();
			inter.setResult(proportion * 100 + "%");
		} else {
			Interface inter = new Interface();
			inter.setErrcode(ICommonConstants.INTERFACEERRO.NOINTERFACE.ordinal());// 不存在此接口
			interfaces.add(inter);
		}
		return interfaces;
	}

	/**
	 * 添加访问日志
	 * 
	 * @param request
	 * @throws IOException
	 */
	@Transactional
	public void addLog(HttpServletRequest request, String remark) {
		String serverLocalFalg = properties.getProperty("serverFlag.local");
		// != false && notnull 是本地服务
		if (serverLocalFalg != null && !"false".equals(serverLocalFalg)) {
			return;
		}
		String userId = request.getHeader("ccd-user-id");// 登录用户id
		User user = null;
		String method = request.getMethod();// 获取method
		if (method != null && "GET".equals(method)) {
			return;
		}
		String action = request.getHeader("action");// 获取事件类型
		String modelName = "";
		String uri = request.getRequestURI();
		String clientIp = "";

		if ("/favicon.ico".equals(uri)) {
			return;
		}

		if (StringUtils.isNotBlank(userId) && CommonUtil.isNumeric(userId)) {
			String tokenOld = ActionContextHolder.getUidTokenHolder().get(userId);
			UserSession userSession = ActionContextHolder.getEvaHolder().get(tokenOld);
			// User user= dataProcessService.findUserById(userId);// huibati
			// 获取当前user 通过 usersession
			if (userSession != null) {
				user = new User();
				BeanUtils.copyProperties(userSession, user);
			}
		}
		if (uri.indexOf("api") > -1) {
			String[] strs = uri.split("/");
			modelName = strs[2];
		}
		try {
			clientIp = getIpAddr(request);
		} catch (Exception e) {
			logger.debug(e.toString());
		}
		ReqLog log = new ReqLog();
		log.setUser(user);
		log.setAction(action);
		log.setMethod(method);
		log.setModelName(modelName);
		log.setUri(uri);
		log.setClientIp(clientIp);
		log.setCreateTime(CommonUtil.getCurrTimes());
		log.setRemark(remark);
		//ActionContextHolder.getLogQueue().addReqLog(log);
		this.em.persist(log);
		logger.debug("添加访问日志");

	}

	/**
	 * 获取ip地址
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	public String getIpAddr(HttpServletRequest request) throws Exception {
		String ip = request.getHeader("X-Real-IP");
		if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个IP值，第一个为真实IP。
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		} else {
			return request.getRemoteAddr();
		}
	}

	/**
	 * 用户信息统计(呼叫数量，客服经验小时数)
	 */
	/*
	 * @Transactional public void updateUserExtendCall(User user){ Integer
	 * callNumber = 0;// 呼叫数量 Integer workHour = 0;// 客服经验（小时数） Userextend
	 * userextend = this.em.find(Userextend.class,user.getExtendInfo().getId());
	 * Long callNum = (Long)this.em.createQuery(
	 * "select count(c.id) from Call c where c.agent.id = ?1 and c.status.id = ?2"
	 * ) .setParameter(1,user.getId()) .setParameter(2,
	 * ActionContextHolder.getDicctypeHolder().get("callEnd").getId())
	 * .getSingleResult(); if(callNum != null){ callNumber = (int)(long)callNum;
	 * } Long workTimes = (Long)this.em.createQuery(
	 * "select sum (c.duration) from Call c where c.agent.id = ?1 and c.status.id = ?2"
	 * ) .setParameter(1,user.getId()) .setParameter(2,
	 * ActionContextHolder.getDicctypeHolder().get("callEnd").getId())
	 * .getSingleResult(); if(workTimes != null){ workHour =
	 * (int)(long)workTimes/3600 + 1; } userextend.setCallNumber(callNumber);
	 * userextend.setWorkHour(workHour); this.em.merge(userextend);
	 * 
	 * 
	 * }
	 */

	/**
	 * 用户信息统计(任务数)
	 */
	/*
	 * @Transactional public void updateUserExtendTaskNum(User user){ Integer
	 * taskNumber = 0;// 任务数 Userextend userextend =
	 * this.em.find(Userextend.class,user.getExtendInfo().getId()); Long taskNum
	 * = (Long)this.em.createQuery(
	 * "select count(u.id) from UserTask u where u.status.id = ?1")
	 * .setParameter(1,ActionContextHolder.getDicctypeHolder().get(
	 * "taskApplySucc").getId()) .getSingleResult(); if(taskNum != null){
	 * taskNumber = (int)(long)taskNum; } userextend.setTaskNumber(taskNumber);
	 * this.em.merge(userextend); }
	 */

	/**
	 * 判断用户是否已验证
	 * 
	 * @return
	 */
	public boolean checkUserIsVerify(Long userId) {
		boolean flag = false;
		User user = this.em.find(User.class, userId);
		if (user.getStatus() == ICommonConstants.IDCERTIFICATION.CERTIFYSUCCESS.ordinal()) {
			flag = true;
		}
		return flag;
	}

	/**
	 * 获取用户消息列表
	 * 
	 * @param requestParams
	 * @return
	 */
	public Iterable<Message> getUserMessageList(final QueryParams requestParams) {
		ArrayList<Message> messageList = new ArrayList<Message>();
		// 获取参数map
		Map<String, String> keyMap = CommonUtil.getKeyMapByFilter(requestParams);
		String userID = (String) keyMap.get("toUser.id");
		String typeStr = "";
		String type = (String) keyMap.get("type");
		String type1 = (String) keyMap.get("type1");
		if (type != null && !type.isEmpty() && type1 != null && !type1.isEmpty()) {
			typeStr = "'" + type + "','" + type1 + "'";
		} else if (type != null && !type.isEmpty()) {
			typeStr = "'" + type + "'";
		} else if (type1 != null && !type1.isEmpty()) {
			typeStr = "'" + type1 + "'";
		}
		Map<RestrictedPaginationKeys, Integer> pagintion = requestParams.getPagination();// 获取分页参数
		int currPage = PageInfo.getInstance().getCurrPage();// 当前页
		int pageSize = PageInfo.getInstance().getSize();// 分页条数
		if (pagintion.get(RestrictedPaginationKeys.number) != null) {
			currPage = pagintion.get(RestrictedPaginationKeys.number);
		}
		if (pagintion.get(RestrictedPaginationKeys.size) != null) {
			pageSize = pagintion.get(RestrictedPaginationKeys.size);
		}

		String query = "SELECT * FROM (SELECT * FROM ccd_message m WHERE m.to_user = '" + Long.parseLong(userID)
				+ "' AND m.type IN (" + typeStr
				+ ") ORDER BY m.create_time DESC) message GROUP BY message.from_user ORDER BY message.create_time DESC ";

		Query qu = (Query) this.em.createNativeQuery(query, Message.class);
		qu.setFirstResult((currPage - 1) * pageSize);
		qu.setMaxResults(pageSize);
		List list = qu.getResultList();

		for (int i = 0; i < list.size(); i++) {
			Message message = (Message) list.get(i);
			// 发送人id
			long fromUserID = message.getFromUser().getId();
			Short hasRead = 0;// 是否已读 1是0否
			Short messageType = message.getType();
			String query1 = "select count(m.id) from Message m where m.toUser.id = ?1 and m.type = '" + messageType
					+ "' and m.fromUser.id = ?3 and m.hasRead = ?4";
			// 未读消息数量
			int count = (int) (long) this.em.createQuery(query1).setParameter(1, Long.parseLong(userID))
					.setParameter(3, fromUserID).setParameter(4, hasRead).getSingleResult();
			message.setNum(count);
			// message.setRemark(Integer.toString(count));
			messageList.add(message);
		}

		String query1 = "select count(distinct m.fromUser.id) from Message m where m.toUser.id = ?1 and m.type IN ("
				+ typeStr + ")";
		int totalCount = (int) (long) this.em.createQuery(query1).setParameter(1, Long.parseLong(userID))
				.getSingleResult();// 总条数

		int startNum = PageInfo.getInstance().getStartNum(); // 当前页开始条数
		int endNum = pageSize - 1;// 当前页结束条数

		int totalPage = (totalCount + pageSize - 1) / pageSize; // 计算总页数
		if (currPage > totalPage)
			currPage = totalPage;
		startNum = pageSize * (currPage - 1) + 1;// 计算当前页开始条数
		endNum = startNum + pageSize - 1; // 计算当前页结束条数
		if (endNum > totalCount)
			endNum = totalCount;

		// 设置分页信息
		PageInfo.getInstance().setTotalCount(totalCount);
		PageInfo.getInstance().setCurrPage(currPage);
		PageInfo.getInstance().setSize(pageSize);
		PageInfo.getInstance().setTotalPage(totalPage);
		PageInfo.getInstance().setStartNum(startNum);
		PageInfo.getInstance().setEndNum(endNum);

		return messageList;
	}

	/**
	 * 待拨打客户分配
	 */
	public boolean allotCustomer(QueryParams requestParams) {
		logger.debug("进入待拨打客户方法");
		boolean flag = false;
		// ArrayList<CsCustomer> csCustomers = new ArrayList<CsCustomer>();
		Map<String, String> map = CommonUtil.getKeyMapByFilter(requestParams);
		String csId = map.get("cs.id");
		String taskId = map.get("customer.task.id");
		List list = this.em.createQuery("select c from Customer c where c.isAllocated = ?1 and c.task.id = ?2")
				.setParameter(1, (short) ICommonConstants.ISALLOCATED.FALSE.ordinal())
				.setParameter(2, Long.parseLong(taskId)).getResultList();
		if (list.size() > 0) {
			Customer customer = (Customer) list.get(0);
			customer.setIsAllocated((short) ICommonConstants.ISALLOCATED.TRUE.ordinal());
			dslJpaService.setEntityClass(Customer.class);
			dslJpaService.update(customer);
			User cs = this.em.find(User.class, Long.parseLong(csId));
			CsCustomer csCustomer = new CsCustomer();
			csCustomer.setCs(cs);
			csCustomer.setCustomer(customer);
			csCustomer.setStatus(ICommonConstants.COMPLETIONSTATUS.FALSE.ordinal());
			dslJpaService.setEntityClass(CsCustomer.class);
			dslJpaService.create(csCustomer);
			// csCustomers.add(csCustomer);
			logger.debug("成功分配客户");
			flag = true;
		}
		return flag;
	}

	/**
	 * 获取可建工单客户
	 * 
	 * @return
	 */
	public List<CsCustomer> getCustomer(QueryParams requestParams) {
		logger.debug("进入获取可建工单客户方法");
		Map<String, String> map = CommonUtil.getKeyMapByFilter(requestParams);
		String csId = map.get("cs.id");
		String taskId = map.get("customer.task.id");
		List<Long> csCustomerIds = new ArrayList<Long>();
		csCustomerIds = (ArrayList) this.em
				.createNativeQuery("SELECT c.id FROM ccd_cs_customer c WHERE c.cs_id = ?1 AND c.customer_id IN "
						+ "(SELECT cu.id FROM  ccd_customer cu WHERE cu.task_id = ?2 AND cu.id NOT IN "
						+ "(SELECT w.customer_id FROM ccd_workorder w WHERE w.is_success = ?3))")
				.setParameter(1, Long.parseLong(csId)).setParameter(2, Long.parseLong(taskId))
				.setParameter(3, ICommonConstants.WORKORDERSTATUS.NOT.ordinal()).getResultList();

		ArrayList<CsCustomer> csCustomers = new ArrayList<>();
		if (csCustomerIds.size() > 0) {
			String Ids = csCustomerIds.toString().replaceAll("\\[", "").replaceAll("\\]", "");
			logger.debug("ids : " + Ids);
			csCustomers = (ArrayList) this.em.createQuery("select c from CsCustomer c where c.id in (" + Ids + ")")
					.getResultList();
		}
		logger.debug("获取可建工单客户 size : " + csCustomers.size());
		return csCustomers;
	}

	public List<CsCustomer> test() {
		logger.debug("进入获取可建工单客户方法");
		String csId = "2";
		String taskId = "47";
		List<Long> csCustomerIds = new ArrayList<Long>();
		csCustomerIds = (ArrayList) this.em
				.createNativeQuery("SELECT c.id FROM ccd_cs_customer c WHERE c.cs_id = ?1 AND c.customer_id IN "
						+ "(SELECT cu.id FROM  ccd_customer cu WHERE cu.task_id = ?2 AND cu.id NOT IN "
						+ "(SELECT w.customer_id FROM ccd_workorder w WHERE w.is_success = ?3))")
				.setParameter(1, Long.parseLong(csId)).setParameter(2, Long.parseLong(taskId))
				.setParameter(3, ICommonConstants.WORKORDERSTATUS.NOT.ordinal()).getResultList();

		ArrayList<CsCustomer> csCustomers = new ArrayList<>();
		if (csCustomerIds.size() > 0) {

			String Ids = csCustomerIds.toString().replaceAll("\\[", "").replaceAll("\\]", "");
			logger.debug(Ids);
			csCustomers = (ArrayList) this.em.createQuery("select c from CsCustomer c where c.id in (" + Ids + ")")
					.getResultList();
		}

		logger.debug("获取可建工单客户 size : " + csCustomers.size());
		return csCustomers;
	}

}
